package s;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import cbir.Img;
import cbir.Rss;

import com.aetrion.flickr.Flickr;
import com.aetrion.flickr.FlickrException;
import com.aetrion.flickr.REST;
import com.aetrion.flickr.photos.Photo;
import com.aetrion.flickr.photos.PhotoList;
import com.aetrion.flickr.photos.PhotosInterface;
import com.aetrion.flickr.photos.SearchParameters;
import com.aetrion.flickr.tags.Tag;
import com.aetrion.flickr.tags.TagsInterface;
import java.sql.Statement;

public class QBT extends HttpServlet{

		private static final long serialVersionUID = 1L;
		private Properties props;
		private String propsPath;
		private static final int numResults = 25;

		@Override
		public void init(ServletConfig config) throws ServletException {
			super.init(config);
			
			this.propsPath = this.getServletContext().getRealPath("/");
			this.props = new Properties();
			try {
				props.loadFromXML(new FileInputStream(propsPath + "properties.properties"));
			} catch (FileNotFoundException e) {e.printStackTrace();} 
			catch (IOException e) {e.printStackTrace();}
	}
	
		@SuppressWarnings("deprecation")
		@Override
		protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

			String t = req.getQueryString().substring(req.getQueryString().indexOf("=")+1, req.getQueryString().length());
			
			ArrayList<Img> imgs = new ArrayList<Img>();
			LinkedList<String> tags = new LinkedList<String>();
			
			boolean finish = false;
			while(finish == false){
						if(t.indexOf("%2C") == -1){
							tags.add(URLDecoder.decode( t.replaceAll("%20", " ") ) );
							finish = true;
						}else{
							tags.add(URLDecoder.decode( t.substring(0, t.indexOf("%2C%20")).replaceAll("%20", " ") ) );
							t = t.substring(t.indexOf("%2C")+6, t.length());
						}
			}

			String query = "SELECT img.Filename, img.Height, img.Width, x.c as numTagging " +
									"FROM img,  (SELECT u.IdImg as id, count(*) as c " +
														"FROM (";
			
			for(int i = 0; i < tags.size() -1; i++){
					query = query.concat("SELECT imgTag.IdImg as IdImg " +
														"FROM imgTag " +
														"WHERE imgTag.IdTag = (SELECT tag.IdTag FROM tag WHERE tag.Tag = '" + tags.get(i) +"') " +
														"UNION ALL ");
			}
			
			query = query.concat("SELECT imgTag.IdImg as IdImg " +
														"FROM imgTag " +
														"WHERE imgTag.IdTag = (SELECT tag.IdTag FROM tag WHERE tag.Tag = '" + tags.get(tags.size()-1)+"') " + 
														 ") u " +
															"GROUP BY u.IdImg " +
															"ORDER BY c DESC) x " +
															"WHERE img.IdImg = x.id; ");

			
			int numResultsDB = 0;
			Connection cc = null;
			try {
				Class.forName("com.mysql.jdbc.Driver");
				cc= DriverManager.getConnection(props.getProperty("DB_URL"), props.getProperty("DB_USER"), props.getProperty("DB_PASS"));
					Statement ss = (Statement) cc.createStatement();
					ResultSet rs = ss.executeQuery(query);
					
					while(rs.next()){
							Img tmp = new Img(rs.getString("Filename"), "", "", "",  req.getServerName(), req.getContextPath());
							tmp.setHeight(rs.getInt("Height"));
							tmp.setWidth(rs.getInt("Width"));
							imgs.add(tmp);
							numResultsDB++;
					}
			} catch (SQLException e) {e.printStackTrace();} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			finally {
				try {cc.close();} 
				catch (SQLException e) {e.printStackTrace();}
			}
			
			int numRisultatiFlickr;
			
			if(numResultsDB < numResults/2){
				numRisultatiFlickr = numResults - numResultsDB;
			}else{
				numRisultatiFlickr = (int) Math.floor(numResults/2);
			}
			
			String tt = "";
			try {
				tt = obtainFromFlickr(imgs, numRisultatiFlickr, (String[])tags.toArray(new String[tags.size()]));
			} 
			catch (ParserConfigurationException e) {e.printStackTrace();} 
			catch (URISyntaxException e) {e.printStackTrace();} 
			catch (SAXException e) {e.printStackTrace();} 
			catch (FlickrException e) {e.printStackTrace();}
			
			Rss r = new Rss(getServletName(), req.getServerName(), req.getContextPath());
			r.createRssWithoutClosingIt(imgs);
			
			String response = r.getRss() + tt + "</channel></rss>";
			PrintWriter pw = res.getWriter();
			pw.print(response);
		}

		
		@SuppressWarnings("unchecked")
		private String obtainFromFlickr(ArrayList<Img> imgs, int n, String[] tags) throws ParserConfigurationException, URISyntaxException, IOException, SAXException, FlickrException{
						
				//Set api key
				String key=props.getProperty("FLICKR_KEY");
				String svr=props.getProperty("FLICKR_URL");
				REST rest=new REST();
				rest.setHost(svr);
	
				//initialize Flickr object with key and rest
			    Flickr flickr=new Flickr(key,rest);
			    Flickr.debugStream=false;
		    
			    SearchParameters searchParams=new SearchParameters();
			    searchParams.setTagMode("all");
			    searchParams.setTags(tags);
			    
			    //Initialize PhotosInterface object
			    PhotosInterface photosInterface=flickr.getPhotosInterface();
			    
			    //Execute search with entered tags
			    PhotoList photoList = null;
;
				try {photoList = photosInterface.search(searchParams,n,1);} 
				catch (IOException e) {e.printStackTrace();} 
				catch (SAXException e) {e.printStackTrace();} 
				catch (FlickrException e) {e.printStackTrace();}

		    
			    if(photoList!=null){
				       for(int i=0;i<photoList.size();i++){
					          Photo photo=(Photo)photoList.get(i);
					          photo.setSecret(photo.getSecret());
						      String img = photo.getMediumUrl();
						      String title = photo.getTitle();
						      String url = photo.getUrl();
						      Img tmp = new Img(title, "", img, url);
						      imgs.add(tmp);
				       }
			    }else{}
		    
			    String tt = "<cbir:relatedTags>";
				TagsInterface ti=new TagsInterface("d053cd39acc6940f7965dea8292c4300","bd05fef610ccf010",rest);
				Iterator<Tag> it = null;

				
				Collection<Tag>[] collections = new Collection[tags.length];
				ArrayList<String> queue = new ArrayList<String>();
				int[] num = new int[tags.length];
				int[] inserted = new int[tags.length];
				
				for(int j = 0; j < tags.length; j++){
					collections[j] = ti.getRelated(tags[j]);
					num[j] = collections[j].size();
					it = collections[j].iterator();
					
					inserted[j] = 0;
					for(int i = 0; i < Math.ceil(10/tags.length) && it.hasNext() && queue.size() < 10; i++){
						queue.add( ((Tag)(it.next())).getValue() );
						inserted[j]++;
					}
				}
				
				boolean exit = false;
				boolean end = false;
				
				if(queue.size() < 10){
					for(int j = 0; j < tags.length && exit == false; j++){
						while(end == false){
							if(num[j] == 0 || queue.size() == 10 || inserted[j] == num[j] ){
								end = true;
							}
							else{
								queue.add( ((Tag[]) collections[j].toArray(new Tag[collections[j].size()]))[inserted[j]++].getValue() );
							}
						}
						if(queue.size() == 10)
							exit = true;
					}
				}				
				if(queue.size() > 0){
					for(int j = 0; j < (10>queue.size()?queue.size():10) ; j++){
						tt = tt.concat("<cbir:tag>"+queue.get(j)+"</cbir:tag>");
					}
				}				
				tt = tt.concat("</cbir:relatedTags>");
			    return tt;
		}
}